package ycyc.Games.gomoku3;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.border.EmptyBorder;

public class Negamax {
	private static int MAX = SCORE.FIVE * 10;
	private static int MIN = -1 * MAX;
	private int total = 0, // 总节点数
				steps = 0, // 总步数
				count, // 每次思考的节点数
				PVcut, ABcut, // AB剪枝次数
				cacheCount = 0, // zobrist缓存节点数
				cacheGet = 0; // zobrist缓存命中数量
	private int checkmateDeep = Config.checkmateDeep;
	public Point m(Integer deep) {
		deep = deep == null ? Config.searchDeep : deep;
		// 迭代加深
		// 注意这里不要比较分数的大小，因为深度越低算出来的分数越不靠谱，所以不能比较大小，而是是最高层的搜索分数为准
		Point result = new Point();
		for (int i = 2; i <= deep; i += 2) {
			result = maxmin(i);
			if (Math.greatOrEqualThan(result.getScore(), SCORE.FOUR))
				return result;
		}
		return result;
	}

	public Point maxmin(int deep,int _checkmateDeep){
		  float best = MIN;
		  List<Point> points = Board.gen();
		  List<Point> bestPoints =new ArrayList<Point>();
		  int count = 0;
		  ABcut = 0;
		  PVcut = 0;
		  checkmateDeep = (_checkmateDeep == -1 ? checkmateDeep : _checkmateDeep);

		  
		  for(int i=0;i<points.size();i++) {
		    Point p = points.get(i);
		    Board.put(p, Role.com,false);
		    float v = - max(deep-1, -MAX, -best, Role.hum);

		    //边缘棋子的话，要把分数打折，避免电脑总喜欢往边上走
		    if(p.getX()<3 || p.getX() > 11 || p.getY() < 3 || p.getY() > 11) {
		      v = 0.5f * v;
		    }

		    //console.log(v, p);
		    //如果跟之前的一个好，则把当前位子加入待选位子
		    if(Math.equal(v, best)) {
		      bestPoints.add(p);
		    }
		    //找到一个更好的分，就把以前存的位子全部清除
		    if(Math.greatThan(v, best)) {
		      best = v;
		      bestPoints = Collections.EMPTY_LIST;
		      bestPoints.add(p);
		    }
		    Board.remove(p);
		  }
		  System.out.println("分数:"+best.toFixed(3)+", 待选节点:"+JSON.stringify(bestPoints));
		  var result = bestPoints[Math.floor(bestPoints.length * Math.random())];
		  result.score = best;
		  steps ++;
		  total += count;
		  System.out.println("搜索节点数:"+ count+ ",AB剪枝次数:"+ABcut + ", PV剪枝次数:" + PVcut + ", 缓存命中:" + (cacheGet / cacheCount).toFixed(3) + "," + cacheGet + "/" + cacheCount + ",算杀缓存命中:" + (debug.checkmate.cacheGet / debug.checkmate.cacheCount).toFixed(3) + "," + debug.checkmate.cacheGet + "/"+debug.checkmate.cacheCount); //注意，减掉的节点数实际远远不止 ABcut 个，因为减掉的节点的子节点都没算进去。实际 4W个节点的时候，剪掉了大概 16W个节点
		  System.out.println("当前统计：总共"+ steps + "步, " + total + "个节点, 平均每一步" + Math.round(total/steps) +"个节点");
		  System.out.println("================================");
		  return result;

		
	}
}
